package com.qst.util;


import com.qst.beans.OrderItem;
import java.util.*;

public class Recomend {

    private Map<Integer, Set<Integer>> arrayListMap ;
    private Map<Integer, Integer> userID;//辅助存储每一个用户的商品ID映射
    private Map<Integer, Integer> idUser;//辅助存储每一个商品ID对应的用户映射
    Map<Integer, Integer> userItemLength = new HashMap<>();//存储每一个用户对应的不同物品总数  eg: A 3
    Set<Integer> items = new HashSet<>();//辅助存储物品集合
    Map<Integer, Set> puRelation = new HashMap<>();//建立物品到用户的倒排表 eg: a A B

    private ArrayList<Integer> proIds = new ArrayList<>();//存储物品ID

    private int[][] sparseMatrix ;


    public void recomend(ArrayList<OrderItem> orderItemArrayListo, Integer uid){
        userID = new HashMap<>();
        idUser = new HashMap<>();

        Set<Integer> uNum = this.getUNum(orderItemArrayListo);
        System.out.println(uNum.toString()+"uNum.size:"+uNum.size());
        if(uNum.size() > 1){
            this.sparseMatrix = new int[uNum.size()][uNum.size()];

            puRelation = this.getPURelation(orderItemArrayListo);
            System.out.println("upRelation:"+puRelation.toString());
            Set<Integer> keySet = puRelation.keySet();
            int index = 0;
            for(Iterator iterator = keySet.iterator(); iterator.hasNext();){
                Integer next = (Integer) iterator.next();
//                Set set = puRelation.get(next);
                userID.put(next, index);
                idUser.put(index, next);
                index ++;
            }
            System.out.println("userID:"+userID.toString());
            System.out.println("idUser:"+idUser.toString());
            //获取物品的集合
            for(OrderItem orderItem:orderItemArrayListo){
                if(!items.contains(orderItem.getPid())){
                    items.add(orderItem.getPid());
                }
            }
            System.out.println("item:"+items.toString());
            //计算相似度
            getsimilarity(puRelation, uid);

            getRecommendDegree(uid);
        }


    }

    /**
     * 获取所有的用户ID
     * @param orderItemArrayListo
     * @return
     */
    private Set<Integer> getUNum(ArrayList<OrderItem> orderItemArrayListo){
        HashSet<Integer> set = new HashSet<>();
        for(OrderItem item : orderItemArrayListo){
            if(!set.contains(item.getUid())){
                set.add(item.getUid());
            }
        }
        return set;
    }

    /**
     * 建立物品-用户关系表
     * @param orderItemArrayListo
     * @return
     */
    private Map<Integer, Set> getPURelation(ArrayList<OrderItem> orderItemArrayListo){
        HashMap<Integer, Set> map = new HashMap<>();//建立物品到用户的倒排表 eg: a A B
        for(OrderItem orderItem : orderItemArrayListo){
            if(!map.containsKey(orderItem.getPid())){//没有包含这个商品ID作为组件
                HashSet<Integer> integers = new HashSet<>();
                map.put(orderItem.getPid(),integers);
            }
            userItemLength.put(orderItem.getUid(), orderItem.getPid());
        }
        System.out.println("userItemLenth:"+userItemLength.toString());
        for(OrderItem orderItem : orderItemArrayListo){
            Integer id = orderItem.getPid();
            if(map.containsKey(id)){
                map.get(id).add(orderItem.getUid());
            }
        }
        return map;
    }

    /**
     * 计算相似度
     * @param upRelation
     */
    private void getsimilarity(Map<Integer, Set> upRelation, Integer uid){
        Set<Map.Entry<Integer, Set>> entrySet = upRelation.entrySet();
        Iterator<Map.Entry<Integer, Set>> iterator = entrySet.iterator();
        while(iterator.hasNext()){
            Set<Integer> commonUsers = iterator.next().getValue();
            for (Integer user_u : commonUsers) {
                for (Integer user_v : commonUsers) {
                    if(user_u.equals(user_v)){
                        continue;
                    }
                    System.out.println(user_u+"user_u,"+userID.get(user_u)+","+user_v+":user_v,"+userID.get(user_v));
                    this.sparseMatrix[userID.get(user_u)][userID.get(user_v)] += 1;//计算用户u与用户v都有正反馈的物品总数
                }
            }
        }

        for(int i = 0; i < sparseMatrix.length; i++){
            if(i != uid){
                System.out.println(idUser.get(uid)+"--"+idUser.get(i)+"相似度:"+sparseMatrix[uid][i]/Math.sqrt(userItemLength.get(idUser.get(uid))*userItemLength.get(idUser.get(i))));
            }
        }
    }

    /**
     * 计算推荐指数
     */
    private void getRecommendDegree(Integer uid){
        for(Integer integer : items){
            Set<Integer> set = puRelation.get(integer);//得到购买当前物品的所有用户集合
            if(!set.contains(uid)){//如果被推荐用户没有购买当前物品，则进行推荐度计算
                double itemRecommendDegree = 0.0;
                for(Integer user: set){
                    itemRecommendDegree += sparseMatrix[userID.get(uid)][userID.get(user)]/Math.sqrt(userItemLength.get(uid)*userItemLength.get(user));//推荐度计算
                }
                proIds.add((int) itemRecommendDegree);
                System.out.println("The item "+integer+" for "+uid +"'s recommended degree:"+itemRecommendDegree);
            }
        }
    }


}

